import { 
  AmbientLight,
  BoxGeometry,
  Color,
  CylinderGeometry,
  IcosahedronGeometry,
  LatheGeometry,
  Mesh,
  MeshBasicMaterial,
  MeshLambertMaterial,
  OctahedronGeometry,
  ParametricGeometry,
  PerspectiveCamera, 
  PlaneGeometry, 
  Scene, 
  SphereGeometry, 
  SpotLight, 
  TetrahedronGeometry, 
  TorusGeometry, 
  TorusKnotGeometry, 
  Vector3, 
  WebGLRenderer 
} from "three";
import { ParametricGeometries } from 'three/examples/jsm/geometries/ParametricGeometries'
import { ConvexGeometry } from 'three/examples/jsm/geometries/ConvexGeometry'
import { SceneUtils } from 'three/examples/jsm/utils/SceneUtils'
import { TrackballControls } from 'three/examples/jsm/controls/TrackballControls'

const scene = new Scene

const camera = new PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.set(-50, 30, 20)
camera.lookAt(new Vector3(-10, 0, 0))

const renderer = new WebGLRenderer({ antialias: true })
renderer.setClearColor(new Color(0x000000))
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true


// 添加光源
const ambientLight = new AmbientLight(0x555555)
scene.add(ambientLight)

const spotLight = new SpotLight(0xffffff, 1.2, 150, Math.PI / 4, 0, 2)
spotLight.shadow.mapSize.height = 2048
spotLight.shadow.mapSize.width = 2048
spotLight.position.set(-40, 30, 30)
spotLight.castShadow = true
scene.add(spotLight)

addGeometries(scene)

document.body.appendChild(renderer.domElement)

// 创建平面 
const planeGeometry = new PlaneGeometry(60, 40, 1, 1)
const planeMaterial = new MeshLambertMaterial({ color: 0xffffff })
const plane = new Mesh(planeGeometry, planeMaterial)
plane.receiveShadow = true
plane.rotation.x = -0.5 * Math.PI
plane.position.set(0, 0, 0)
scene.add(plane)

const trackballControls = new TrackballControls(camera, renderer.domElement)
render()

function render() {
  trackballControls.update()

  requestAnimationFrame(render)
  renderer.render(scene, camera)
}

function addGeometries(scene: Scene): void {
  let geoms = []

  // 圆柱几何体
  geoms.push(new CylinderGeometry(2, 4, 4))

  // 立方几何体
  geoms.push(new BoxGeometry(3, 2, 2))

  // 球几何体
  geoms.push(new SphereGeometry(3, 16, 16))

  // 二十面几何体
  geoms.push(new IcosahedronGeometry(4))

  let points = [
    new Vector3(2, 2, 2),
    new Vector3(2, 2, -2),
    new Vector3(-2, 2, -2),
    new Vector3(-2, 2, 2),
    new Vector3(2, -2, 2),
    new Vector3(2, -2, -2),
    new Vector3(-2, -2, -2),
    new Vector3(-2, -2, 2),
  ]

  // 凸包几何体
  geoms.push(new ConvexGeometry(points))

  // 车削几何体
  // http://en.wikipedia.org/wiki/Lathe_(graphics)
  let pts = []
  let detail = .1
  let radius = 3
  for (let angle = 0.0; angle < Math.PI; angle+= detail)
    pts.push(new Vector3(Math.cos(angle) * radius, 0, Math.sin(angle) * radius))
  geoms.push(new LatheGeometry(pts, 12))

  // 八面几何体
  geoms.push(new OctahedronGeometry(3))

  // 参数化几何体
  geoms.push(new ParametricGeometry(ParametricGeometries.mobius3d, 20, 10))

  // 四面几何体
  geoms.push(new TetrahedronGeometry(3))

  // 圆环几何体
  geoms.push(new TorusGeometry(3, 1, 10, 20))

  // 圆环扭结几何体
  geoms.push(new TorusKnotGeometry(3, 0.2, 100, 3))

  let j = 0
  for (let i = 0; i < geoms.length; i++) {
    let cubeMaterial = new MeshLambertMaterial({
      wireframe: true,
      color: Math.random() * 0xffffff
    })

    let materials = [
      new MeshLambertMaterial({
        color: Math.random() * 0xffffff
      }),
      new MeshBasicMaterial({
        color: 0xf5f5f5,
        wireframe: true
      })
    ]

    let mesh = SceneUtils.createMultiMaterialObject(geoms[i], materials)
    mesh.traverse(e => {
      e.castShadow = true
    })

    mesh.position.x = -24 + ((i % 4) * 12)
    mesh.position.y = 4
    mesh.position.z = -8 + (j * 12)

    if ((i + 1) % 4 == 0) j++

    scene.add(mesh)
  }
}